package javalangspec;

import java.util.List;

public class Immutability {
	public static void main(String[] args) {
//		Mutable mutable = new Mutable(0);
//		for (int i = 0; i < 1000; i++) {
//			new MutableRacer("Thread#"+i, mutable).start();
//		}
		
		Immutable immutable = new Immutable(2);
		for (int i = 0; i < 1000; i++) {
			new ImmutableRacer("Thread#"+i, immutable).start();
		}
	}
}

class MutableRacer extends Thread {

	Mutable target;
	
	public MutableRacer(String name, Mutable target) {
		super(name);
		this.target = target;
	}

	@Override
	public void run() {
		target.add(1);
		target.add(1);
		target.add(1);
		target.add(1);
		target.add(1);
		System.out.println(getName() + ": " + target);
	}
}

class ImmutableRacer extends Thread {

	Immutable target;
	
	public ImmutableRacer(String name, Immutable target) {
		super(name);
		this.target = target;
	}

	@Override
	public void run() {
		target.add(1);
		target.add(1);
		target.add(1);
		target.add(1);
		target.add(1);
		System.out.println(getName() + ": " + target);
	}
}

class Mutable {
	private List<Integer> values;
	
	public Mutable(List<Integer> values) {
		this.values = values;
	}
	
	public List<Integer> add(List<Integer> values) {
		this.values.addAll(values);
		return this.values;
	}
	
	public Integer getValue() {
		return value;
	}
	
	@Override
	public String toString() {
		return "Mutable[" + value + "]";
	}
}

class Immutable {
	private Integer value;
	
	public Immutable(Integer value) {
		this.value = value;
	}
	
	public Immutable add(Integer value) {
//		try {
//			Thread.sleep((long) (Math.random()*10));
//		} catch (InterruptedException e) { }
		int newValue = this.value + value;
		return new Immutable(newValue);
	}
	
	public Integer getValue() {
		return value;
	}
	
	@Override
	public String toString() {
		return "Immutable[" + value + "]";
	}
}
